#pragma once
#include <iostream>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PATHNAME "."
#define PROJID 0x66
#define SIZE 4096
#define EXIT(x)    \
    do             \
    {              \
        perror(x); \
        exit(1);   \
    } while (0)
#define CREATER 0
#define USER 1

class shm
{
private:
    void _get_key()
    {
        _key = ftok(_pathname.c_str(), _proj_id);
        if (_key < 0)
        {
            EXIT("ftok");
        }
    }
    void _creat(int flg)
    {
        _shmid = shmget(_key, _size, flg);
        if (_shmid < 0)
        {
            EXIT("shmget");
        }
    }
    void _connect()
    {
        _start_addr = shmat(_shmid, nullptr, 0);
        if ((long long)_start_addr < 0)
        {
            EXIT("shmat");
        }
    }
    void _delete_connect()
    {
        if (_start_addr == 0)
            return;
        shmdt(_start_addr);
        _start_addr = nullptr;
    }
    void _destroy() // 释放共享内存
    {
        if (_shmid < 0)
            return;
        shmctl(_shmid, IPC_RMID, 0);
    }

public:
    shm(const std::string &pathname, int proj, int id)
        : _shmid(-1), _key(-1), _size(SIZE), _proj_id(proj), _pathname(pathname), _start_addr(nullptr), _id(id)
    {
        // 生成key
        _get_key();
        // 创建/获取共享内存
        int flg;
        if (_id == USER)
            flg = IPC_CREAT;
        else if (id == CREATER)
            flg = IPC_CREAT | IPC_EXCL | 0666;
        _creat(flg);
        // 连接共享内存
        _connect();
    }
    ~shm()
    {
        // 去连接
        _delete_connect();
        // 释放共享内存
        if (_id == CREATER)
            _destroy();
    }
    void *_get_addr()
    {
        return _start_addr;
    }

private:
    int _shmid;
    int _key;
    int _size;
    int _proj_id;
    std::string _pathname;
    void *_start_addr;
    int _id;
};

// class shm
// {
// public:
//     shm() : _shmid(-1), _key(-1), _size(SIZE), _proj_id(PROJID), _pathname(PATHNAME), _start_addr(nullptr)
//     {
//     }
//     ~shm() {}
//     void _creat() // 创建共享内存
//     {
//         // 生成key值
//         _key = ftok(_pathname.c_str(), _proj_id);
//         if (_key < 0)
//         {
//             EXIT("ftok");
//         }
//         printf("key : %d\n", _key);
//         _shmid = shmget(_key, _size, IPC_CREAT | IPC_EXCL | 0666);
//         if (_shmid < 0)
//         {
//             EXIT("shmget");
//         }
//         std::cout << "shmget success" << std::endl;
//     }
//     void _get() // 获取共享内存
//     {
//         // 生成key值
//         _key = ftok(_pathname.c_str(), _proj_id);
//         if (_key < 0)
//         {
//             EXIT("ftok");
//         }
//         printf("key : %d\n", _key);
//         // 获取共享内存--共享内存已经存在
//         _shmid = shmget(_key, _size, IPC_CREAT);
//         if (_shmid < 0)
//         {
//             EXIT("shmget");
//         }
//         std::cout << "shmget success" << std::endl;
//     }
//     bool _connect() // 连接共享内存
//     {
//         if (_shmid < 0)
//             return false;
//         _start_addr = shmat(_shmid, nullptr, 0);
//         if ((long long)_start_addr < 0)
//         {
//             EXIT("shmat");
//         }
//         std::cout << "connect success" << std::endl;
//         return true;
//     }
//     void _delete_connect() // 去连接
//     {
//         int n = shmdt(_start_addr);
//         if (n < 0)
//         {
//             EXIT("shmdt");
//         }
//         std::cout << "shmdt success" << std::endl;
//     }
//     void _destroy() // 释放共享内存
//     {
//         int n = shmctl(_shmid, IPC_RMID, 0);
//         if (n < 0)
//         {
//             EXIT("shmctl");
//         }
//         std::cout << "destroy success" << std::endl;
//     }
//     void *_get_addr() // 获取起始虚拟地址
//     {
//         return _start_addr;
//     }

// private:
//     int _shmid;
//     int _key;
//     int _size;
//     int _proj_id;
//     std::string _pathname;
//     void *_start_addr;
// };

// #pragma once
// #include <iostream>
// #include <sys/ipc.h>
// #include <sys/shm.h>
// #include <unistd.h>

// #define PATHNAME "."
// #define PROJ_ID 0x66
// #define EXIT(x)    \
//     do             \
//     {              \
//         perror(x); \
//         exit(1);   \
//     } while (0)
// #define CREATE 0
// #define USER 1

// const int shm_size = 4096;
// class shm
// {
// private:
//     key_t _getkey()
//     {
//         key_t key = ftok(_pathname.c_str(), _proj_id);
//         if (key < 0)
//         {
//             EXIT("ftok");
//         }
//         return key;
//     }
//     void _creat(int mode)
//     {
//         _shmid = shmget(_key, _size, mode);
//         if (_shmid < 0)
//         {
//             EXIT("shmget");
//         }
//     }
//     //
//     void _get()
//     {
//         _key = _getkey();
//         // 创建共享内存
//         if (_id == CREATE)
//             _creat(IPC_CREAT | IPC_EXCL | 0666);
//         else if (_id == USER)
//             _creat(IPC_CREAT);
//     }
//     // 连接共享内存
//     void _connect()
//     {
//         _start_addr = shmat(_shmid, nullptr, 0);
//         if ((long long)_start_addr < 0)
//         {
//             EXIT("shmat");
//         }
//     }
//     // 释放共享内存
//     void _destroy()
//     {
//         if (_shmid < 0)
//             return;
//         int n = shmctl(_shmid, IPC_RMID, nullptr);
//         if (n < 0)
//         {
//             EXIT("shmctl");
//         }
//         std::cout << "destroy success" << std::endl;
//         // printf("destroy shm success\n");
//     }

// public:
//     shm(int id, const std::string &pathname, int proj)
//         : _id(id), _pathname(pathname), _proj_id(proj), _shmid(-1), _size(shm_size), _key(-1), _start_addr(nullptr)
//     {
//         _get();
//         _connect();
//     }
//     ~shm()
//     {
//         if(_id == CREATE)
//         {
//             _destroy();
//         }
//     }
//     void *_get_start_addr()
//     {
//         return _start_addr;
//     }

// private:
//     int _id; // 身份
//     std::string _pathname;
//     int _proj_id;
//     int _shmid;
//     int _size;
//     key_t _key;
//     void *_start_addr;
// };

/*class shm
{
public:
    shm() : _shmid(-1), _size(shm_size), _key(-1), _pathname(PATHNAME), _proj_id(PROJ_ID),_start_addr(nullptr)
    {
    }
    ~shm() {}
    // 创建共享内存
    void _creat()
    {
        // 生成key值
        _key = ftok(_pathname.c_str(), _proj_id);
        if (_key < 0)
        {
            EXIT("ftok");
        }
        printf("key : %x\n", _key);
        // 创建共享内存
        _shmid = shmget(_key, _size, IPC_CREAT | IPC_EXCL | 0666);
        if (_shmid < 0)
        {
            EXIT("shmget");
        }
        printf("shmid : %d\n", _shmid);
    }
    // 获取共享内存
    void _getshm()
    {
        // 生成key
        _key = ftok(_pathname.c_str(), _proj_id);
        if (_key < 0)
        {
            EXIT("ftok");
        }
        printf("key : %x\n", _key);
        _shmid = shmget(_key, _size, IPC_CREAT);
        if (_shmid < 0)
        {
            EXIT("shmget");
        }
        printf("shmid : %d\n", _shmid);
    }
    void _connect()
    {
        _start_addr = shmat(_shmid, nullptr, 0);
        if((long long) _start_addr < 0)
        {
            EXIT("shmat");
        }
    }
    void* _get_start_addr()
    {
        return _start_addr;
    }
    // 释放共享内存
    void _destroy()
    {
        if (_shmid < 0)
            return;
        int n = shmctl(_shmid, IPC_RMID, nullptr);
        if (n < 0)
        {
            EXIT("shmctl");
        }
        std::cout << "destroy success" << std::endl;
        // printf("destroy shm success\n");
    }

private:
    int _shmid;
    int _size;
    key_t _key;
    std::string _pathname;
    int _proj_id;
    void* _start_addr;
};*/